# 与 activity 相关的视图

from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
# 导入模型
from sa.models import User, Project, Activity
# 导入对应的序列化器
from sa.serializers.activitySerializer import ActivitySerializer

import logging

# 日志记录对象
logger = logging.getLogger('django')


class ActivityInfoGenericAPIView(GenericAPIView):
    # 指定序列化器类
    serializer_class = ActivitySerializer
    # 定义基础的查询集，使用 select_related 优化查询，
    # 预先加载关联的 project 和 creator 对象
    queryset = Activity.objects.all().select_related(
        'project', 'creator'
    )
    permission_classes = [IsAuthenticated]

    # 重写父类的 get_queryset 方法
    def get_queryset(self):
        # 在DRF中 self.kwargs 是一个字典，包含了从 URL 路由中捕获的命名参数。
        # self.kwargs['project_pk'] 从 URL 中获取项目 ID
        # 当访问 /projects/123/activities/ 时
        # self.kwargs['project_pk'] 会直接得到 '123'（字符串或转换后的类型，如 int）
        # 这里不能使用 request.query_params.get 方法，URL 的查询字符串（即 ?key=value 部分）

        # 检查 project_pk 是否存在于 kwargs 中
        # 从 URL 路由中捕获的命名参数
        if 'project_pk' not in self.kwargs:
            return self.queryset.none()  # 返回空查询集
        project_pk = self.kwargs['project_pk']

        # 过滤出当前project下的所有 activities
        # 提前在所有activity筛选出 project_pk, project_id 是关联字段默认增加的字段
        return super().get_queryset().filter(project_id=project_pk).order_by('-id')

    def get(self, request, project_pk):
        """获取项目下的所有activities"""
        # 获取查询集,父类重写了 self.get_queryset(), 增加了project_id的过滤
        activities = self.get_queryset()
        serializer = self.get_serializer(instance=activities, many=True)
        return Response(data=serializer.data)

    def post(self, request, project_pk):
        """在项目下创建新activity"""
        # 项目是否存在
        try:
            project = Project.objects.get(pk=project_pk)
        except Project.DoesNotExist:
            return Response(
                {'error': 'Project not found'},
                status=status.HTTP_404_NOT_FOUND
            )
        # 检查权限
        current_user = request.user
        if (project.creator != current_user
                and not project.participants.filter(id=current_user.id).exists()):
            return Response(
                data={'error': '当前登录用户无权限操作'},
                status=status.HTTP_403_FORBIDDEN
            )
        # 开始执行反序列化
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(data=serializer.data, status=status.HTTP_201_CREATED)


class ActivityDetailGenericAPIView(GenericAPIView):
    serializer_class = ActivitySerializer
    # 定义基础的查询集，使用 select_related 优化查询，
    # 预先加载关联的 project 和 creator 对象
    queryset = Activity.objects.all().select_related(
        'project', 'creator'
    )
    permission_classes = [IsAuthenticated]

    # 根据路由重写lookup_field, 默认是pk, 告诉 DRF 使用这个字段作为查询条件
    # lookup_field = 'id'  # 数据库字段名
    # lookup_url_kwarg = 'activity_pk'  # 保持 activity_pk 作为 URL 参数名

    # 重写父类方法
    def get_queryset(self):
        # self.kwargs 检查URL里是否有project_pk
        if 'project_pk' not in self.kwargs:
            # 返回空查询集
            return self.queryset.none()
        project_pk = self.kwargs['project_pk']
        return super().get_queryset().filter(project_id=project_pk)

    def get(self, request, project_pk, pk):
        """ 查询单个activity """
        try:
            instance = self.get_object()
        except Activity.DoesNotExist:
            return Response(data={'error': '没有找到此activity！'},
                            status=status.HTTP_404_NOT_FOUND)
        # 增加项目参与者也可以查看activity
        if (instance.creator == request.user or
                instance.project.creator == request.user or
                instance.project.participants.filter(id=request.user.id).exists()):
            # 序列化器对象
            serializer = self.get_serializer(instance=instance)
            return Response(data=serializer.data)
        else:
            return Response(data={'error': '没有查看activity的权限'},
                            status=status.HTTP_403_FORBIDDEN)

    def put(self, request, project_pk, pk):
        """ 修改 activity """
        try:
            instance = self.get_object()
        except Activity.DoesNotExist:
            return Response(data={'error': '没有找到此activity！'},
                            status=status.HTTP_404_NOT_FOUND)
        if (instance.creator == request.user
                or instance.project.creator == request.user):
            serializer = self.get_serializer(instance=instance, data=request.data)
            serializer.is_valid(raise_exception=True)
            serializer.save()
            logger.info(f"{request.user.cn_name} 成功更新activity {instance.pk}")
            return Response(data=serializer.data, status=status.HTTP_200_OK)
        else:
            return Response(data={'error': '没有更新此activity的权限'},
                            status=status.HTTP_403_FORBIDDEN)

    def delete(self, request, project_pk, pk):
        """删除项目下的指定activity"""
        current_user = request.user
        try:
            instance = self.get_object()
        except Activity.DoesNotExist:
            return Response(data={'error': '没有找到此activity！'},
                            status=status.HTTP_404_NOT_FOUND)
        if (instance.creator == current_user
                or instance.project.creator == current_user):
            # 执行删除
            instance.delete()
            logger.info(f"{current_user} 成功删除activity {instance.pk}")
            return Response(status=status.HTTP_204_NO_CONTENT)
        else:
            return Response(data={'error': '没有删除此activity的权限'},
                            status=status.HTTP_403_FORBIDDEN)


class ActivityTypeChoicesAPIView(APIView):
    """Activity 工作分类"""

    def get(self, request):
        get_choices = Activity._meta.get_field('activity_type').choices
        # 列表推导式
        options = [{'value': value, 'label': label} for value, label in get_choices]
        return Response(data=options)
